/****************************************************************************
**
** Copyright (C) 2011 Jesús Martínez Pérez
**
** This program is free software: you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the 
** Free Software Foundation, either version 3 of the License, or (at your
** option) any later version.
**
** This program is distributed in the hope that it will be useful, but 
** WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
** for more details.
**
** You should have received a copy of the GNU General Public License along 
** with this program. If not, see <http://www.gnu.org/licenses/>
**
****************************************************************************/
#include <deflate.h>


Deflate::Deflate(){
}


Deflate::Deflate(Vbits v1,LZ77 l){
	lz=l;
	vb=v1;
}


int Deflate::Size()const{
	return vb.Size();
}


int Deflate::tamano()const{
	return lz.tamvc();
}


void Deflate::CodLZ(){
	lz.Codifica();
}


void Deflate::CodDeflate(){	
	bool fin=false;
	VD_unsignedint vi;	
	vi=lz.Getvi();
	VD_unsignedchar vc;
	vc=lz.Getvc();	
	Vbits vaux(0);
	vaux.Add(1);
	vaux.Add(1);
	vaux.Add(0);		
	tabla t1(1);
	tabla t2(2);
	tabla t3(3);
	tabla t4(4);		
	for(unsigned int  i=0; !fin; i++){
		if(vi[i]<257){
			VD_unsignedchar vdlit=0;
			vdlit.Add(vi[i]);
			Vbits vlit(t3.GetVb(vi[i]));
			vlit.Invertir();
			vaux+=vlit;
			if(vi[i]==256){
				fin=true;
			}	
		}	
		if(vi[i]>256){
			Vbits vlong(0);
			int codigolong=t1.codigo(vi[i]-254);		
			//cout<<"vi[i] es "<<vi[i]-254<<endl;// posiciones
			if(codigolong!=285){
				vlong=t1.GetVb(vi[i]-254);
			}
			Vbits vl=t3.GetVb(codigolong);
			vl.Invertir();
			vaux+=vl;
			//cout<<"se inserta long:"<<vl<<" , "<<vlong<<endl;//longitud
			if(vlong.Size()>0){
				vaux+=vlong;
			}
			i++;
			int codigodist=t2.codigo(vi[i]-1);
			Vbits vdist(t2.GetVb(vi[i]-1));
			Vbits vd(t4.GetVb(codigodist));
			vd.Invertir();
			//cout<<"se inserta dist:"<<vd<<" , "<<vdist<<endl;//distancia
			vaux+=vd;
			if(vdist.Size()>0){
				vaux+=vdist;
			}
		}
	}
	vaux.Completar();
	vb=vaux;
}

		
unsigned char Deflate::GetB(int pos)const{
	return vb.Getv(pos);
}


unsigned int Deflate::CRC32()const{
	return lz.CRC32();
}

	
LZ77 Deflate::GetLZ()const{
  	return lz;
}


Vbits Deflate::GetVb()const{
	return vb;
}


istream & operator>>(istream & is,Deflate & def){
	is>>def.lz;
	return is;
}


ostream & operator<<(ostream & os,Deflate & def){
	for(unsigned long int i=0;i<def.vb.Size();i++){
			(i%8==0)?os<<endl:os<<def.vb.Get(i);
	}
	os<<endl;
	os<<def.lz;
	return os;
}
